package com.example.bottomdrawer;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.nfc.Tag;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

public class BottomDrawer extends ViewGroup {
    //只要drawer里的控件没有点击事件,该控件就能滑动drawer，有点击事件和按钮不会触发滑动

    private int mCloseHeightSeen;//抽屉关闭时看到的高度，默认100dp
    private int mContenterId;
    private int mDrawerId;
    
    private View mContenterView;
    private View mDrawerView;
    private boolean isOpen = false;
    private float mDownY;//用于记录滑动开始的位置
    private float mTanslationY;//Y上的偏移量
    private long mMaxDuration = 700;//从关闭到完全打开/打开到完全关闭需要的ms
    private OnDrawerCloseOpenListener mOnDrawerCloseOpenListener = null;//对外的接口

    public BottomDrawer(Context context) {
        this(context, null);
    }

    public BottomDrawer(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BottomDrawer(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BottomDrawer);
        mCloseHeightSeen = (int) typedArray.getDimension(R.styleable.BottomDrawer_closeHeightSeen, dpToPx(context, 100f));
        mContenterId = typedArray.getResourceId(R.styleable.BottomDrawer_contenter, -1);
        mDrawerId = typedArray.getResourceId(R.styleable.BottomDrawer_drawer, -1);
        typedArray.recycle();
        //Log.d("bottomdrawer", "ch ==> " + mCloseHeightSeen);
        //Log.d("bottomdrawer", "getcontenterid ==> " + mContenterId);
    }

    //一定要包含两个子view，而且要设contenter和drawer
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        View child0 = getChildAt(0), child1 = getChildAt(1);
        if (child0.getId() == mContenterId) {
            mContenterView = child0;
            mDrawerView = child1;
        } else {
            mContenterView = child1;
            mDrawerView = child0;
        }
        /*
        Log.d("bottomdrawer",  "child0id ==> " + child0.getId());
        Log.d("bottomdrawer",  "child1id ==> " + child1.getId());
        Log.d("bottomdrawer",  "contenterid ==> " + mContenterView.getId() +",drawerid" + mDrawerView.getId());
         */

        //设置drawer的touch事件
        mDrawerView.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return onTouchDrawer(v, event);
            }
        });
    }

    //drawer的touch事件处理
    private boolean onTouchDrawer(View v, MotionEvent event) {
        switch (event.getAction()) {//event.geetY/X是以像素为单位，随着setTranslationY，坐标原点也在不断改变，getTranslationY是原来位置的相对距离
            case MotionEvent.ACTION_DOWN:
                //Log.d("bottomdrawer", "mTanslationY ==> " + mTanslationY);
                //Log.d("bottomdrawer", "downY ==> " + event.getY());
                mDownY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float dY = event.getY() - mDownY;
                if (mTanslationY + dY >= - (mDrawerView.getMeasuredHeight() - mCloseHeightSeen) && mTanslationY + dY <= 0) {
                    mTanslationY += dY;
                    mDrawerView.setTranslationY(mTanslationY);//移动后，手指的y依旧是down的y
                }
                //Log.d("bottomdrawer", "afterY ==> " + event.getY());
                //Log.d("bottomdrawer", "dY ==> " + dY);
                break;
            case MotionEvent.ACTION_UP:
                //Log.d("bottomdrawer", "mTanslationY ==> " + mTanslationY);
                //Log.d("bottomdrawer", "upY ==> " + event.getY());
                if  (isOpen == false) {
                    if (mTanslationY > - (mDrawerView.getMeasuredHeight() / 5)) {
                        close();
                    } else {
                        open();
                    }
                } else {
                    if (mTanslationY < - (mDrawerView.getMeasuredHeight() - mCloseHeightSeen) + mDrawerView.getMeasuredHeight() / 5) {
                        open();
                    } else {
                        close();
                    }
                }
                break;
        }
        return true;//返回false即会处理touch也会处理click，返回true就不会处理click
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//这两个参数是BottomDrawer的，每个包含数（宽/高pixel）和模式
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);//this的高size
        //Log.d("botttomdrawer", "w ==> " + widthSize + ", h ==> " + heightSize);
        //测量contenter，宽跟父控件一样，高(1，指定高；2，包裹；3匹配
        LayoutParams contentLayoutParams = mContenterView.getLayoutParams();
        int contenterHeight = contentLayoutParams.height;//获取contenter的高
        int contenterHeightMeasureSpec;
        if (contenterHeight == LayoutParams.WRAP_CONTENT) {//高是包裹内容
            contenterHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
        } else if (contenterHeight == LayoutParams.MATCH_PARENT) {//高是匹配父控件
            contenterHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
        } else {//高是指定大小
            contenterHeightMeasureSpec = MeasureSpec.makeMeasureSpec(contenterHeight, MeasureSpec.EXACTLY);
        }
        mContenterView.measure(widthMeasureSpec, contenterHeightMeasureSpec);//与BottomDrawer同宽

        //测量drawer，宽跟父控件一样，高(1，指定高；2，包裹；3匹配
        LayoutParams drawerLayoutParams = mContenterView.getLayoutParams();
        int drawerHeight = drawerLayoutParams.height;//获取drawer的高
        int drawerHeightMeasureSpec;
        if (drawerHeight == LayoutParams.WRAP_CONTENT) {//高是包裹内容
            drawerHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
        } else if (drawerHeight == LayoutParams.MATCH_PARENT) {//高是匹配父控件
            //Log.d("botttomdrawer", "heightsize ==> " + heightSize);
            drawerHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
        } else {//高是指定大小
            drawerHeightMeasureSpec = MeasureSpec.makeMeasureSpec(drawerHeight, MeasureSpec.EXACTLY);
        }
        mDrawerView.measure(widthMeasureSpec, drawerHeightMeasureSpec);//与this同宽
        //Log.d("botttomdrawer", "drawerheight ==> " + MeasureSpec.getSize(drawerHeightMeasureSpec));

        //测量自己
        setMeasuredDimension(widthSize, heightSize);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //先摆放contenter
        mContenterView.layout(0,0,mContenterView.getMeasuredWidth(), mContenterView.getMeasuredHeight());//getMeasuredHeight()是以像素为单位
        //Log.d("botttomdrawer", "w ==> " + mContenterView.getMeasuredWidth() + ", h ==> " + mContenterView.getMeasuredHeight());

        //再摆放drawer
        mDrawerView.layout(0,
                mContenterView.getMeasuredHeight() - mCloseHeightSeen,
                mDrawerView.getMeasuredWidth(),
                mContenterView.getMeasuredHeight() - mCloseHeightSeen + mDrawerView.getMeasuredHeight());
        //Log.d("botttomdrawer", "top ==> " + (mContenterView.getMeasuredHeight() - mCloseHeightSeen));
        //Log.d("botttomdrawer", "drawerheight ==> " + mDrawerView.getMeasuredHeight());
    }

    public void close() {
        float proportion = Math.abs(( - mTanslationY) / (mDrawerView.getMeasuredHeight() - mCloseHeightSeen));
        ObjectAnimator animator = ObjectAnimator.ofFloat(mDrawerView, "translationY", 0);
        animator.setDuration((long) (proportion * mMaxDuration));
        animator.start();//这个动画并不会改变getTranslationY，要手动记录改变
        mTanslationY = 0;
        isOpen = false;
        if (mOnDrawerCloseOpenListener != null) {
            mOnDrawerCloseOpenListener.onDrawerClose(this.isOpen);
        }
        //Log.d("bottomdrawer", "close,proportion ==> " + proportion);
    }

    public void open() {
        float proportion = Math.abs((mTanslationY - (mCloseHeightSeen - mDrawerView.getMeasuredHeight())) /(mDrawerView.getMeasuredHeight() - mCloseHeightSeen));
        ObjectAnimator animator = ObjectAnimator.ofFloat(mDrawerView, "translationY", - (mDrawerView.getMeasuredHeight() - mCloseHeightSeen));
        animator.setDuration((long) (proportion * mMaxDuration));
        animator.start();
        mTanslationY = - (mDrawerView.getMeasuredHeight() - mCloseHeightSeen);
        isOpen = true;
        if (mOnDrawerCloseOpenListener != null) {
            mOnDrawerCloseOpenListener.onDrawerOpen(this.isOpen);
        }
        //Log.d("bottomdrawer", "open,proportion ==> " + proportion);
    }

    public boolean isOpen() {
        return isOpen;
    }

    public void setOnDrawerCloseOpenListener(OnDrawerCloseOpenListener listener) {
        this.mOnDrawerCloseOpenListener = listener;
    }

    public interface OnDrawerCloseOpenListener {

        void onDrawerClose(boolean isOpen);

        void onDrawerOpen(boolean isOpen);

    }

    private int dpToPx(Context context, float dpValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}
